#include "OSMsg.h"
#include "MutexLock.h"

#define NOW	(((_tcb*)(run->content))->pPro)
#define NOWT	((_tcb*)(run->content))
#define _KHEAPAPPLY(x)			(Kmalloc(&kmemory,x))
#define _KHEAPRELEA(x)			(Kfree(&kmemory,x))
extern volatile _mch kmemory;
extern volatile ring* run;

  void SendMessage(_pcb* pHandle,unsigned long mark,unsigned long* argv,unsigned long args)
  {
    _msg* buff = Kmalloc(&kmemory,sizeof(_msg));
    buff->from = NOWT;
    buff->mark = mark;
    unsigned long* copyargv = NULL;
    if(args != 0)
      {
	copyargv = Kmalloc(&kmemory,args * sizeof(unsigned long));
	unsigned int i;			
	for(i = 0 ; i < args ; i++)
	  copyargv[i] = argv[i];
      }
    buff->args = args;
    buff->argv = copyargv;
    buff->next = NULL;
    MUTEX_LOCK(&(pHandle->msgboxLocker));
    _msg* pointer = pHandle->msgbox;
    //Mutex Area
    if(pointer == NULL)
      {
	pHandle->msgbox = buff;
      }
    else
      {

	while(pointer->next != NULL)
	  pointer = pointer->next;
	pointer->next = buff;	

      }
    //Mutex Area end	
    MUTEX_UNLOCK(&(pHandle->msgboxLocker));
  }

  _hook* SetHookToMessage(_pcb* from,_pcb* fHandle,unsigned long mark,void (*fun)(struct THRECB*,unsigned long,unsigned long*,unsigned long))
  {
    _hook* buff = Kmalloc(&kmemory,sizeof(_hook));
    buff->from = fHandle;
    buff->mark = mark;
    buff->fun = fun;
    buff->next = NULL;
    MUTEX_LOCK(&(fHandle->hooksLocker));
    //Mutex Area
    if(from->hooks == NULL)
      {
	from->hooks = buff;
      }
    else
      {
	buff->next = from->hooks;
	from->hooks = buff;
      }
    //Mutex Area end
    MUTEX_UNLOCK(&(fHandle->hooksLocker));
    return buff;
  }
  
  void DeleteHookToMessage(_hook* handle)
  {
    MUTEX_LOCK(&(fHandle->hooksLocker));
    _hook* pointer = NOW->hooks;
    if(pointer == NULL) return;

    //Mutex Area
    while(pointer ->next != NULL)
      {
	if(pointer ->next == handle)
	  {
	    pointer->next = handle->next;
	    Kfree(&kmemory,handle);
	    break;
	  }
	pointer = pointer->next;

      }
    MUTEX_UNLOCK(&(fHandle->hooksLocker));
    //Mutex Area end
  }
  void DeleteAllHookToMessage(_hook* handle)
  {
    MUTEX_LOCK(&(fHandle->hooksLocker));
    if(handle->next != NULL)
      DeleteAllHookToMessage(handle->next);
    _KHEAPRELEA(handle);
    MUTEX_UNLOCK(&(fHandle->hooksLocker));
  }
  void CheckMessage() //unfinished
  {
    MUTEX_LOCK(&(pHandle->msgboxLocker));
    _msg* pointer = NOW->msgbox;
    _hook* hk;
    //Mutex Area
    while(pointer != NULL)
      {
	_msg* next = pointer->next;
	_msg* movedmessage = Kmalloc(&(NOW->mhandle),sizeof(_msg));
	_Memcpy(pointer,movedmessage,sizeof(_msg));
	_KHEAPRELEA(pointer);
	pointer = movedmessage;
	//Move In the message
	hk = NOW->hooks;
	while(hk != NULL)
	  {
	    if(hk->from == ALL_PROCESS 
	       || MessageMask(hk->mark) == ALL_MESSAGE 
	       || hk->from == pointer->from->pPro 
	       || MessageMask(hk->mark) == pointer->mark)
	      {	
		//TODO:
		//Create a thread at the very last of the ring
		//hk->fun(pointer->from,pointer->mark,pointer->argv,pointer->args);
		unsigned int* argv = Kmalloc(&kmemory,sizeof(unsigned int*) * 6);
		_pcb* proc;
		/*				if(NOW == (IFD[0]))
						{
						proc =	((_astr)(pointer->argv))->funcpage;
						}
						else
		*/				{
		  proc = NOW;
		}
		//pointer->argv == struct abs_stream* 
		argv[0] = proc->flPage;
		argv[1] = pointer->from;
		argv[2] = pointer->mark;
		argv[3] = pointer->argv;
		argv[4] = pointer->args;
		argv[5] = pointer;
		CreateMsgThread(proc,hk->fun,argv+1,5);			
	      }
	    hk = hk->next;
	  }
	pointer = next;
      }
    //Mutex Area End
    MUTEX_UNLOCK(&(pHandle->msgboxLocker));
  }
  void DeleteMessage(_msg* message)
  {

    if(message->args != 0)
      {
	Kfree(&kmemory,message->argv);
      }
    Kfree(&kmemory,message);

  }
  void DeleteAllMessage(_msg* message)
  {
    if(message->next != NULL)
      {
	DeleteAllMessage(message->next);
      }
    if(message->args != 0)
      Kfree(&kmemory,message->argv);
	
    _KHEAPRELEA(message);
  }
  int SendText(_tcb* thr,unsigned int text)
  {
    if(thr->text != NULL) return 0;
    thr->text = Kmalloc(&kmemory,sizeof(unsigned int));
    *thr->text = text;
    return 1;
  }
  int GetText(_tcb* thr,unsigned int* text)
  {
    if(thr->text == NULL) return 0;
    *text = *thr->text;
    Kfree(&kmemory,NOWT->text);
    return 1;
  }


